<template>
    <view class="tui-tab" :class="[isSticky ? 'tui-tab-sticky' : '']">
        <scroll-view
            class="tui-scroll__view"
            :class="[isFixed ? 'tui-tabs__fixed' : '']"
            :style="{
                height: height + 'rpx',
                background: backgroundColor,
                top: isFixed ? top + 'px' : 'auto',
                zIndex: isFixed ? zIndex : 'auto'
            }"
            :scroll-x="scrolling"
            :scroll-with-animation="scrolling"
            :scroll-left="scrollLeft"
        >
            <view class="tui-tabs__wrap">
                <view
                    class="tui-tabs__list"
                    :class="[scroll ? 'tui-tabs__scroll' : '']"
                    :style="{ height: height + 'rpx' }"
                >
                    <view
                        class="tui-tabs__item"
                        :style="{ height: height + 'rpx' }"
                        v-for="(item, index) in swiperTabs"
                        :key="index"
                        @tap="handleClick"
                        :data-index="index"
                    >
                        <view
                            class="tui-item__child"
                            :style="{
                                color:
                                    currentTab == index ? selectedColor : color,
                                fontSize: size + 'rpx',
                                lineHeight: size + 'rpx',
                                fontWeight:
                                    bold && currentTab == index
                                        ? 'bold'
                                        : 'normal'
                            }"
                            >{{ item.tabName }}</view
                        >
                    </view>
                    <view
                        class="tui-tabs__line"
                        :class="[needTransition ? 'tui-transition' : '']"
                        :style="{
                            background: sliderBgColor,
                            height: sliderHeight,
                            borderRadius: sliderRadius,
                            bottom: bottom,
                            width: lineWidth + 'px',
                            transform: `translateX(${translateX}px)`
                        }"
                    ></view>
                </view>
            </view>
        </scroll-view>
    </view>
</template>

<script>
export default {
    name: 'tuiTab',
    props: {
        // 标签页数据源
        swiperTabs: {
            type: Array,
            default() {
                return []
            }
        },
        // 当前选项卡
        current: {
            type: Number,
            default: 0
        },
        // 是否可以滚动
        scroll: {
            type: Boolean,
            default: false
        },
        // tab高度 rpx
        height: {
            type: Number,
            default: 80
        },
        backgroundColor: {
            type: String,
            default: '#fff'
        },
        //字体大小
        size: {
            type: Number,
            default: 28
        },
        //字体颜色
        color: {
            type: String,
            default: '#666'
        },
        //选中后字体颜色
        selectedColor: {
            type: String,
            default: '#5677fc'
        },
        //选中后 是否加粗 ，未选中则无效
        bold: {
            type: Boolean,
            default: false
        },
        //滑块高度
        sliderHeight: {
            type: String,
            default: '2px'
        },
        //滑块背景颜色
        sliderBgColor: {
            type: String,
            default: '#5677fc'
        },
        //滑块 radius
        sliderRadius: {
            type: String,
            default: '2px'
        },
        //滑块bottom
        bottom: {
            type: String,
            default: '0'
        },
        //是否固定
        isFixed: {
            type: Boolean,
            default: false
        },
        //isFixed=true时，tab top值 px
        top: {
            type: Number,
            // #ifndef H5
            default: 0,
            // #endif
            // #ifdef H5
            default: 44
            // #endif
        },
        zIndex: {
            type: [Number, String],
            default: 996
        },
        //是否开启粘性布局
        isSticky: {
            type: Boolean,
            default: true
        }
    },
    watch: {
        /**
         * 监听数据变化, 如果改变重新初始化参数
         */
        swiperTabs(newVal, oldVal) {
            this.scrolling = false
            // 异步加载数据时候, 延迟执行 init 方法, 防止无法正确获取 dom 信息
            setTimeout(() => this.init(), 0)
        },
        /**
         *  监听 currentTab 变化, 做对应处理
         */
        current(newVal, oldVal) {
            this.scrollByIndex(newVal)
        }
    },
    created() {
        this.currentTab = this.current
    },
    mounted() {
        this.init()
    },
    data() {
        return {
            /* 未渲染数据 */
            windowWidth: 0, // 屏幕宽度
            tabItems: [], // 所有 tab 节点信息

            /* 渲染数据 */
            scrolling: true, // 控制 scroll-view 滚动以在异步加载数据的时候能正确获得 dom 信息
            needTransition: false, // 下划线是否需要过渡动画
            translateX: 0, // 下划 line 的左边距离
            lineWidth: 0, // 下划 line 宽度
            scrollLeft: 0, // scroll-view 左边滚动距离
            currentTab: 0
        }
    },
    methods: {
        /**
         * 切换菜单
         */
        handleClick(e) {
            let index = Number(e.currentTarget.dataset.index)
            this.$emit('slideTuiTab', {
                index: index
            })
            this.scrollByIndex(index)
        },
        /**
         * 滑动到指定位置
         * @param tabCur: 当前激活的tabItem的索引
         * @param needTransition: 下划线是否需要过渡动画, 第一次进来应设置为false
         */
        scrollByIndex(tabCur, needTransition = true) {
            let item = this.tabItems[tabCur]
            if (!item) return
            let itemWidth = item.width || 0,
                itemLeft = item.left || 0
            this.needTransition = needTransition
            this.currentTab = tabCur
            // 超出滚动的情况
            if (this.scroll) {
                // 保持滚动后当前 item '尽可能' 在屏幕中间
                let scrollLeft = itemLeft - (this.windowWidth - itemWidth) / 2
                this.scrollLeft = scrollLeft
                this.translateX = itemLeft
                this.lineWidth = itemWidth
            } else {
                // 不超出滚动的情况
                this.translateX = itemLeft
                this.lineWidth = itemWidth
            }
        },
        /**
         *  初始化函数
         */
        init() {
            const { windowWidth } = uni.getSystemInfoSync()
            this.windowWidth = windowWidth || 375
            const query = uni.createSelectorQuery().in(this)
            query
                .selectAll('.tui-item__child')
                .boundingClientRect(res => {
                    this.scrolling = true
                    this.tabItems = res
                    this.scrollByIndex(this.currentTab, false)
                })
                .exec()
        }
    }
}
</script>

<style scoped>
.tui-tab-sticky {
    position: sticky;
    top: -1rpx;
    z-index: 100;
}

.tui-scroll__view {
    width: 100%;
    height: 80rpx;
    overflow: hidden;
}

.tui-tabs__fixed {
    position: fixed;
    left: 0;
}

.tui-tabs__wrap {
    padding-bottom: 20rpx;
}

.tui-tabs__list {
    position: relative;
    height: 80rpx;
    display: flex;
}

.tui-tabs__scroll {
    white-space: nowrap !important;
    display: block !important;
}

.tui-tabs__scroll .tui-tabs__item {
    padding: 0 30rpx;
    display: inline-flex;
}

.tui-tabs__scroll .tui-item__child {
    display: block !important;
}

.tui-tabs__item {
    flex: 1;
    text-align: center;
    padding: 0 10rpx;
    box-sizing: border-box;
    transition: color 0.3s ease-in-out;
    display: flex;
    align-items: center;
    justify-content: center;
}

.tui-item__child {
    display: inline-block;
}

.tui-tabs__line {
    position: absolute;
    left: 0;
    width: 0;
    display: inline-block;
}

.tui-tabs__line.tui-transition {
    transition: width 0.3s, transform 0.3s;
}
</style>
